﻿// <copyright file="DataTools.cs" company="Pelican Design &amp; Development">
//      Copyright (c) Pelican Design &amp; Development. All Rights Reserved.
// </copyright>

namespace AppDomains
{
    using System;
    using System.IO;
    using System.Security;
    using System.Security.Permissions;

    /// <summary>
    /// Provides tools to enable sandboxed libraries to access some files.
    /// </summary>
    public static class DataTools
    {
        /// <summary>
        /// Path where sandboxed libraries will store their files.
        /// </summary>
        private static readonly string dataPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Data");

        /// <summary>
        /// Reads a file specified by a file name for a sandboxed element which cannot access files.
        /// </summary>
        /// <param name="fileName">File name without path.</param>
        /// <returns>File contents.</returns>
        [SecuritySafeCritical]
        public static string ReadFileForMe(string fileName)
        {
            FileIOPermission dataDirectoryPermission = new FileIOPermission(PermissionState.None);
            dataDirectoryPermission.AddPathList(FileIOPermissionAccess.AllAccess, dataPath);
            dataDirectoryPermission.Assert();

            ForbidFancyFileNames(fileName);
            return File.ReadAllText(Path.Combine(dataPath, fileName));
        }

        /// <summary>
        /// Writes a file specified by a file name for a sandboxed element which cannot access files.
        /// </summary>
        /// <param name="fileName">File name without path.</param>
        /// <param name="fileContents">File contents.</param>
        [SecuritySafeCritical]
        public static void WriteFileForMe(string fileName, string fileContents)
        {
            Console.WriteLine("Entered common tools library.");
            Console.WriteLine("\tAssering privileges...");

            FileIOPermission dataDirectoryPermission = new FileIOPermission(PermissionState.None);
            dataDirectoryPermission.AddPathList(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Write, dataPath);
            try
            {
                dataDirectoryPermission.Assert();
                Console.WriteLine("\tOk. Privileges asserted.");
                ForbidFancyFileNames(fileName);
                File.WriteAllText(Path.Combine(dataPath, fileName), fileContents);
            }
            catch (InvalidOperationException ex)
            {
                Console.WriteLine("InvalidOperationException: " + ex.Message + ".");
            }
        }

        /// <summary>
        /// Denies file names containing path. For example '../../../Windows/explorer.exe' will be an invalid file name.
        /// </summary>
        /// <param name="fileName">Name of the file, as it was given by the plugin.</param>
        private static void ForbidFancyFileNames(string fileName)
        {
            char[] invalidCharacters = Path.GetInvalidFileNameChars();
            if (fileName.IndexOfAny(invalidCharacters) != -1)
            {
                throw new SecurityException("You cannot use special characters in file name.");
            }
        }
    }
}
